﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MouseExtender.Logic;
using MouseExtender.Logic.Entities;
using MouseExtender.Logic.Events;
using MouseExtender.Logic.Managers;

namespace MouseExtender.Controls.UserControls
{
    /// <summary>
    /// Interaction logic for TabsUC.xaml
    /// </summary>
    public partial class TabsUC : UserControl
    {
        #region dependencies

        public static readonly DependencyProperty CurrentTabProperty = DependencyProperty.Register("CurrentTab", typeof(int), typeof(TabsUC));

        #endregion

        #region events

        public event EventHandler<TabChangedEventArgs> TabChanged = (s, e) => { };

        #endregion

        #region prroperties

        public int CurrentTab
        {
            get
            {
                return (int)this.GetValue(CurrentTabProperty);
            }
            private set
            {
                if (CurrentTab != value)
                {
                    this.SetValue(CurrentTabProperty, value);
                }
            }
        }

        #endregion

        #region constructor

        public TabsUC()
        {
            InitializeComponent();
        }

        #endregion

        #region methods

        public void LoadTabs()
        {
            tabs.ItemsSource = null;
            if (SettingsManager.CurrentSettings.TabInfoList.Count != 0)
            {
                List<TabInfo> tabList = new List<TabInfo>();
                int tabOrderIndex = 0;
                foreach (TabInfo item in SettingsManager.CurrentSettings.TabInfoList)
                {
                    item.OrderIndex = tabOrderIndex++;
                    int colorKey = item.Id < 10 ? item.Id : item.Id % 10;
                    item.Color = TabColors.Colors[colorKey];
                    tabList.Add(item);
                }

                tabs.ItemsSource = tabList;
            }
        }

        public void AddTab(string tabName)
        {
            UserSettings settings = SettingsManager.CurrentSettings;
            int newId = settings.TabInfoList.Count == 0 ? settings.TabInfoList.Count : settings.TabInfoList.Last().Id + 1;

            //Update all exist items if first tab was added.
            if (newId == 0)
            {
                settings.LauncherItems.ForEach(i => i.TabId = 0);
                CurrentTab = 0;
            }

            int colorKey = newId < 10 ? newId : newId % 10;
            TabInfo item = new TabInfo()
            {
                Id = newId,
                Name = tabName,
                Color = TabColors.Colors[colorKey]
            };
            settings.TabInfoList.Add(item);
            settings.SettingChanged();
            LoadTabs();
        }

        public void RemoveTab(int id)
        {
            SettingsManager.CurrentSettings.TabInfoList.RemoveAll(i => i.Id == id);
            SettingsManager.CurrentSettings.LauncherItems.RemoveAll(i => i.TabId == id);
            SettingsManager.CurrentSettings.SettingChanged();
            CurrentTab = SettingsManager.CurrentSettings.TabInfoList.Count > 0 ? SettingsManager.CurrentSettings.TabInfoList[0].Id : -1;
            LoadTabs();
            App.MainWindowInstance.ucLauncher.Refresh(true, null);
            tabs.Focus();
        }

        public void RemoveTab(int id, int moveItemsToTabId)
        {
            SettingsManager.CurrentSettings.TabInfoList.RemoveAll(i => i.Id == id);
            SettingsManager.CurrentSettings.LauncherItems.ForEach(i =>
                {
                    if (i.TabId == id) i.TabId = moveItemsToTabId;
                }
            );
            SettingsManager.CurrentSettings.SettingChanged();
            CurrentTab = moveItemsToTabId;
            LoadTabs();
            App.MainWindowInstance.ucLauncher.Refresh(true, null);
            tabs.Focus();
        }

        public void SetControlWidth()
        {
            double width = App.MainWindowInstance.ucLauncher.ActualWidth - 70;
            if (!double.IsNaN(width) && width > 0)
                tabs.Width = width;
        }

        public void OpenTab(int tabIndex)
        {
            ListBoxItem listBoxItem = (ListBoxItem)tabs.ItemContainerGenerator.ContainerFromIndex(tabIndex);
            Button tabButton = FindTabButton(listBoxItem);
            if (tabButton != null)
            {
                Rectangle tabThumb = (Rectangle)tabButton.Template.FindName("tabThumb", tabButton);
                TextBlock tabTitle = (TextBlock)tabButton.Template.FindName("tabTitle", tabButton);
                if (!tabTitle.Width.Equals(tabTitle.MaxWidth))
                {
                    DoubleAnimation animation = new DoubleAnimation();
                    animation.To = tabTitle.MaxWidth;
                    animation.Duration = new Duration(TimeSpan.FromMilliseconds(100));
                    tabTitle.BeginAnimation(TextBlock.WidthProperty, animation);
                    Pen pen = tabThumb.FindName("thumbPen") as Pen;
                    pen.Brush = tabTitle.Foreground;
                }
            }
        }

        public void CloseTab(int tabIndex)
        {
            ListBoxItem listBoxItem = (ListBoxItem)tabs.ItemContainerGenerator.ContainerFromIndex(tabIndex);
            Button tabButton = FindTabButton(listBoxItem);
            if (tabButton != null)
            {
                Rectangle tabThumb = (Rectangle)tabButton.Template.FindName("tabThumb", tabButton);
                TextBlock tabTitle = (TextBlock)tabButton.Template.FindName("tabTitle", tabButton);
                DoubleAnimation animation = new DoubleAnimation();
                animation.To = 0;
                animation.Duration = new Duration(TimeSpan.FromMilliseconds(100));
                tabTitle.BeginAnimation(TextBlock.WidthProperty, animation);
                Pen pen = tabThumb.FindName("thumbPen") as Pen;
                pen.Brush = TabColors.DefaultColorBrush;
            }
        }

        public void SelectTab(int tabId)
        {
            int tabIndex = GetTabIndexByTabId(tabId, true);
            int currentTabIndex = GetTabIndexByTabId(CurrentTab, true);
            if (CurrentTab != tabId)
            {
                CloseTab(currentTabIndex);
                OpenTab(tabIndex);
            }
            CurrentTab = tabId;
        }

        public int GetTabIndexByTabId(int tabId, bool throwExceptionIfNotFound)
        {
            for (int i = 0; i < tabs.Items.Count; i++)
            {
                TabInfo tabInfo = (TabInfo)tabs.Items[i];
                if (tabInfo.Id == tabId)
                    return i;
            }
            if (throwExceptionIfNotFound)
            {
                string message = String.Format("Tab with Id '{0}' not found.", tabId);
                throw new ApplicationException(message);
            }
            else
            {
                return 0;
            }
        }

        public Button FindTabButton(DependencyObject parent)
        {
            Button tabButton = null;
            while (VisualTreeHelper.GetChildrenCount(parent) > 0)
            {
                tabButton = VisualTreeHelper.GetChild(parent, 0) as Button;
                if (tabButton != null)
                    break;
                else
                    parent = VisualTreeHelper.GetChild(parent, 0);
            }
            return tabButton;
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property == CurrentTabProperty)
            {
                TabChangedEventArgs args = new TabChangedEventArgs();
                if (e.OldValue != null)
                {
                    args.ChangeInfo.PreviousTab = GetTabById((int)e.OldValue);
                }
                args.ChangeInfo.CurrentTab = GetTabById((int)e.NewValue);

                TabChanged(this, args);
            }

            base.OnPropertyChanged(e);
        }

        private static TabInfo GetTabById(int tabId)
        {
            return SettingsManager.CurrentSettings.TabInfoList.Where(ti => ti.Id == tabId).SingleOrDefault();
        }

        #endregion

        #region event handlers

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            CurrentTab = SettingsManager.CurrentSettings.TabInfoList.Count > 0 ? SettingsManager.CurrentSettings.TabInfoList[0].Id : -1;
            SetControlWidth();
            LoadTabs();
        }

        private void tabTitle_Loaded(object sender, RoutedEventArgs e)
        {
            TextBlock tabTitle = (TextBlock)sender;
            tabTitle.MaxWidth = tabTitle.ActualWidth;
            tabTitle.Width = 0;
            int currentIndex = GetTabIndexByTabId(Int32.Parse(tabTitle.Uid), true);
            if (currentIndex == tabs.Items.Count - 1)
            {
                int currentTabIndex = GetTabIndexByTabId(CurrentTab, false);
                OpenTab(currentTabIndex);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            int currentTabIndex = GetTabIndexByTabId(CurrentTab, true);
            int senderTabId = Int32.Parse(button.Uid);
            if (GetTabIndexByTabId(senderTabId, true) != currentTabIndex)
                CloseTab(currentTabIndex);
            CurrentTab = senderTabId;
            //App.MainWindowInstance.ucLauncher.Refresh(true);
        }

        private void Button_MouseEnter(object sender, MouseEventArgs e)
        {
            Button tabButton = (Button)sender;
            Rectangle tabThumb = (Rectangle)tabButton.Template.FindName("tabThumb", tabButton);
            TextBlock tabTitle = (TextBlock)tabButton.Template.FindName("tabTitle", tabButton);
            DoubleAnimation animation = new DoubleAnimation();
            animation.To = tabTitle.MaxWidth;
            animation.Duration = new Duration(TimeSpan.FromMilliseconds(100));
            tabTitle.BeginAnimation(TextBlock.WidthProperty, animation);
            Pen pen = tabThumb.FindName("thumbPen") as Pen;
            pen.Brush = tabTitle.Foreground;
        }

        private void Button_MouseLeave(object sender, MouseEventArgs e)
        {
            Button tabButton = (Button)sender;
            int currentId = Int32.Parse(tabButton.Uid);
            if (CurrentTab != currentId)
            {
                Rectangle tabThumb = (Rectangle)tabButton.Template.FindName("tabThumb", tabButton);
                TextBlock tabTitle = (TextBlock)tabButton.Template.FindName("tabTitle", tabButton);
                DoubleAnimation animation = new DoubleAnimation();
                animation.To = 0;
                animation.Duration = new Duration(TimeSpan.FromMilliseconds(100));
                tabTitle.BeginAnimation(TextBlock.WidthProperty, animation);
                Pen pen = tabThumb.FindName("thumbPen") as Pen;
                pen.Brush = TabColors.DefaultColorBrush;
            }
        }

        #endregion

    }
}
